package com.link.base.base.member.service;

import com.link.base.user.model.CoreUser;
import com.link.base.base.accnt.model.Account;
import com.link.base.base.coupons.model.CollectRecord;
import com.link.base.base.coupons.model.Coupons;
import com.link.base.base.coupons.service.CollectRecordService;
import com.link.base.base.coupons.service.CouponsService;
import com.link.base.base.member.RedisApiUtils;
import com.link.base.base.member.dao.mybatis.mapper.MpMemberMapper;
import com.link.base.base.member.model.MchMpPay;
import com.link.base.base.member.model.MemberAccount;
import com.link.base.base.member.model.MpMember;
import com.link.base.base.member.model.MpWeixinPay;
import com.link.base.base.member.util.MpPayConstants;
import com.link.base.base.member.util.MpPayTools;
import com.link.base.base.mpconfig.model.Mp;
import com.link.base.base.mpconfig.service.MpService;
import com.link.base.base.order.dao.mybatis.mapper.PayRecordMapper;
import com.link.base.base.order.dao.mybatis.mapper.SaleOrderMapper;
import com.link.base.base.order.model.PayRecord;
import com.link.base.base.order.model.SaleOrder;
import com.link.base.base.saleactivity.model.SaleActivity;
import com.link.base.base.saleactivity.service.AccntCampMonitorService;
import com.link.base.base.saleactivity.service.SaleActivityService;
import com.link.core.cllog.LCLogger;
import com.link.base.wechat.payment.model.CoPayToWalletPayment;
import com.link.base.wechat.payment.model.WxPayment;
import com.link.base.wechat.payment.service.WxPaymentService;
import com.link.base.wechat.payment.util.PayUtils;
import com.link.core.basic.dao.KeyGenerateDao;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.DateUtil;
import com.link.core.util.PropertyUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import com.thoughtworks.xstream.XStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 会员
 *
 * @author: 路江
 * @date 2018-10-22
 */
@Service
public class MpMemberServiceImpl extends BasicServiceImpl<MpMember> implements MpMemberService {

    private static final Logger logger = LogManager.getLogger(MpMemberServiceImpl.class);
    /**
     * 红包支付响应标志
     **/
    private static final String RESULT_SUCCESS = "SUCCESS";
    private static final String RESULT_CODE = "result_code";
    private static final String RESULT_ERR_CODE_DES = "err_code_des";
    /**
     * 随机对象
     **/
    private static final Random RANDOM = new Random();

    /**
     * 红包随机金额 redMoneys
     **/
    private static final double[] RED_MONEYS = {0.88, 0.88, 1.98, 0.88, 1.68, 0.88, 1.68, 0.88, 0.88, 2.58, 0.88, 1.68};
    /**
     * 当前小程序登录类型
     */
    private static final String CURRENT_LOGIN_TYPE_MP = "MP";

    @Resource
    private MpMemberMapper mpmemberMapper;

    @Resource
    private SaleOrderMapper saleOrderMapper;

    @Resource
    private PayRecordMapper payRecordMapper;

    @Resource
    private MpService mpService;

    @Resource
    private Environment env;

    @Resource
    private KeyGenerateDao keyGenerateDao;

    @Resource
    private CouponsService couponsService;

    @Resource
    private CollectRecordService collectRecordService;

    @Resource
    private SaleActivityService saleActivityService;

    @Resource
    private AccntCampMonitorService accntCampMonitorService;

    @Override
    public BasicMapper<MpMember> getBasicMapper() {
        return mpmemberMapper;
    }

    @Resource
    private WxPaymentService wxPaymentService;

    /**
     * 统一下单
     *
     * @author: 路江
     * @date 2018-10-22
     * @param mpWeixinPay
     * @return Map
     * @throws Exception
     */
    @Override
    public Map<String, Object> orderMpPay(MpWeixinPay mpWeixinPay, HttpServletRequest request) throws Exception {
        Map<String, Object> result = new HashMap<>(16);
        CoreUser user = UserUtil.getUser();
        // 获取小程序配置参数
        Mp mp = new Mp();
        mp.setAppEncryptionId(user.getIntegrationId());
        mp = mpService.queryMpInfoByEncryptionId(mp);
        // 获取payment对象
        WxPayment wxPayment = this.setMpWxPay(mpWeixinPay, request, mp);
        // 调用统一下单接口,并返回结果
        result = wxPaymentService.unifiedOrder(wxPayment);
        //时间戳
        String timeStamp = PayUtils.getCurrTime();
        String nonceStr = PayUtils.createNonceStr();
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("timeStamp", timeStamp);
        packageParams.put("nonceStr", nonceStr);
        packageParams.put("signType", String.valueOf(PayUtils.SignType.MD5));
        packageParams.put("package", "prepay_id=" + result.get("prepay_id"));
        packageParams.put("appId", wxPayment.getAppId());
        // 将支付参数返回给前端,用于调用jsapi/小程序api
        result.put("paySign", PayUtils.createSign(packageParams, mp.getApiKey()));
        result.put("timeStamp", timeStamp);
        result.put("package", "prepay_id=" + result.get("prepay_id"));
        result.put("nonceStr", nonceStr);
        result.put("appId", wxPayment.getAppId());
        result.put("signType", String.valueOf(PayUtils.SignType.MD5));
        return result;
    }

    /**
     * 生成流水
     *
     * @author: 路江
     * @date 2018-10-22
     * @param map
     * @throws Exception
     */
    @Override
    public void orderPayUpdate(Map map) throws Exception {
        String openid = "openid";
        Account account = new Account();
        if (null != map.get(openid)) {
           // account.setWxOwnOpenId(map.get(openid).toString());
            account = mpmemberMapper.queryAccount(account);
        }
        PayRecord precord = new PayRecord();
        Long orderId;
        String transactionId = "transaction_id";
        String attach = "attach";
        if (null != map.get(transactionId) && null != map.get(attach)) {
            precord.setTransactionNum(map.get(transactionId).toString());
            orderId = (Long) map.get(attach);
            precord.setOrderId(orderId);
        } else {
            throw new ServiceException("MEMBER-004");
        }
        precord = mpmemberMapper.queryPayRecord(precord);

        if (null != precord) {
            throw new ServiceException("MEMBER-005");
        }
        if (null == account) {
            throw new ServiceException("MEMBER-006");
        }
        Long createBy = account.getId();
        Long corpId = account.getCorpid();
        Long acctId = account.getId();
        SaleOrder record = new SaleOrder();
        record.setId(orderId);
        record.setIsPaid("Y");
        record.setPayStatus("Paid");
        //无登陆用户修改信息
        record.interfaceCreateData(createBy, createBy, corpId);
        saleOrderMapper.orderUpdateByInterface(record);
        //生成付款记录
        PayRecord payRecord = new PayRecord();
        //订单id
        payRecord.setOrderId(orderId);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        payRecord.setPayDate(format.format(new Date()));
        //支付类型，支付结束
        payRecord.setPayType("PayIn");
        String totalFee = "total_fee";
        if (null != map.get(totalFee)) {
            Double amount = Double.valueOf(map.get(totalFee).toString()) / 100;
            payRecord.setAmount(amount.toString());
        }
        String outTradeNo = "out_trade_no";
        if (null != map.get(outTradeNo)) {
            payRecord.setOrderNo(map.get(outTradeNo).toString());
        }
        //微信支付
        payRecord.setType("WECHAT");
        if (null != map.get(transactionId)) {
            payRecord.setTransactionNum(map.get(transactionId) + "");
        }
        Long receptionId = keyGenerateDao.keyGenerate();
        payRecord.setPayStatus("FINISHED");
        payRecord.setId(receptionId);
        payRecord.setLoginCorpId(corpId);
        payRecord.setCreatedBy(createBy);
        payRecord.setCorpid(corpId);
        payRecord.interfaceCreateData(createBy, createBy, corpId);
        payRecordMapper.payRecordInsertByInterface(payRecord);
        //修改优惠劵状态
        if (null != orderId) {
            // 查询出订单
            SaleOrder saleOrder = new SaleOrder();
            saleOrder.setLoginCorpId(corpId);
            saleOrder.setId(orderId);
            saleOrder = saleOrderMapper.queryById(saleOrder);
            if (saleOrder == null) {
                throw new ServiceException("MEMBER-007");
            }
            if (null != saleOrder.getCouponsId()) {
                CollectRecord collectRecord = new CollectRecord();
                // 小程序的订单的 couponsId 为领取记录表的id
                collectRecord.setId(saleOrder.getCouponsId());
                collectRecord.setLoginCorpId(corpId);
                collectRecord = collectRecordService.queryById(collectRecord);
                if (collectRecord == null) {
                    throw new ServiceException("MEMBER-008");
                }
                //修改优惠券状态为已使用
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                collectRecord.setUseTime(formatter.format(new Date()));
                collectRecord.setClaimStatus("Used");
                collectRecord.setUserId(acctId);
                collectRecord.interfaceCreateData(createBy, createBy, corpId);
                collectRecordService.collectRecordUpdateByInterface(collectRecord);
            }
            //自提的话改变订单状态为已完成，配送的话改变状态为待发货
            //自提
            String pickedUp = "PICKED_UP";
            //配送
            String mcd = "Merchant distribution";
            if (pickedUp.equals(saleOrder.getDeliverType())) {
                // 已完成
                saleOrder.setStatus("Closed");
            } else if (mcd.equals(saleOrder.getDeliverType())) {
                //代发货
                saleOrder.setStatus("Unshipped");
            }
            //修改订单状态
            saleOrder.interfaceCreateData(createBy, createBy, corpId);
            saleOrderMapper.statusUpdateByInterface(saleOrder);
        }


    }

    @Override
    public String createSign(Map map) throws Exception {
        String transactionId = "transaction_id";
        String nonceStr = "nonce_str";
        String bankType = "bank_type";
        String openid = "openid";
        String feeType = "fee_type";
        String mchId = "mch_id";
        String cashFee = "cash_fee";
        String outTradeNo = "out_trade_no";
        String appid = "appid";
        String totalFee = "total_fee";
        String tradeType = "trade_type";
        String resultCode = "result_code";
        String timeEnd = "time_end";
        String attach = "attach";
        String isSubscribe = "is_subscribe";
        String returnCode = "return_code";
        String key = "xoBZi7adcpkZfxKOjew8FK3JpSQKmbdO";


        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        if (null != map.get(transactionId)) {
            packageParams.put(transactionId, map.get(transactionId).toString());
        }
        if (null != map.get(nonceStr)) {
            packageParams.put(nonceStr, map.get(nonceStr).toString());
        }
        if (null != map.get(bankType)) {
            packageParams.put(bankType, map.get(bankType).toString());
        }
        if (null != map.get(openid)) {
            packageParams.put(openid, map.get(openid).toString());
        }
        if (null != map.get(feeType)) {
            packageParams.put(feeType, map.get(feeType).toString());
        }
        if (null != map.get(mchId)) {
            packageParams.put(mchId, map.get(mchId).toString());
        }
        if (null != map.get(cashFee)) {
            packageParams.put(cashFee, map.get(cashFee).toString());
        }
        if (null != map.get(outTradeNo)) {
            packageParams.put(outTradeNo, map.get(outTradeNo).toString());
        }
        if (null != map.get(appid)) {
            packageParams.put(appid, map.get(appid).toString());
        }
        if (null != map.get(totalFee)) {
            packageParams.put(totalFee, map.get(totalFee).toString());
        }
        if (null != map.get(tradeType)) {
            packageParams.put(tradeType, map.get(tradeType).toString());
        }
        if (null != map.get(resultCode)) {
            packageParams.put(resultCode, map.get(resultCode).toString());
        }
        if (null != map.get(timeEnd)) {
            packageParams.put(timeEnd, map.get(timeEnd).toString());
        }
        if (null != map.get(attach)) {
            packageParams.put(attach, map.get(attach).toString());
        }
        if (null != map.get(isSubscribe)) {
            packageParams.put(isSubscribe, map.get(isSubscribe).toString());
        }
        if (null != map.get(returnCode)) {
            packageParams.put(returnCode, map.get(returnCode).toString());
        }
        String sign = PayUtils.createSign(packageParams, key);
        return sign;
    }

    /**
     * 配置参数
     *
     * @author: 路江
     * @date 2018-10-22
     * @param mpWeixinPay
     * @return
     */
    private WxPayment setMpWxPay(MpWeixinPay mpWeixinPay, HttpServletRequest res, Mp mp) throws Exception {
        CoreUser user = UserUtil.getUser();
        if (user == null) {
            throw new ServiceException("PUBLIC-023");
        }
        SaleOrder saleOrder = new SaleOrder();
        saleOrder.setId(mpWeixinPay.getOderId());
        saleOrder = saleOrderMapper.queryById(saleOrder);

        // 从redis中获取配置的通知地址
        String notifyUrl = PropertyUtil.getCropProperty("wxPaynotifyUrl", mpWeixinPay.getLoginCorpId());
        if (StringUtils.isBlank(notifyUrl)) {
            throw new ServiceException("MEMBER-009");
        }
//        总金额
        Double fee = saleOrder.getOrderAmount() * 100;
        String opennId = user.getOpenId();
//        String notifyUrl = "http://avcttv.natappfree.cc/linkcrm/action/link/mpmember/notify_url";
//        Double fee = 1d;
        return wxPaymentService.getPayment(
                mp.getAppId(),
                mp.getMchId(),
                saleOrder.getOrderNo(),
                notifyUrl,
                fee.intValue(),
                "JSAPI",
                "甄恒零售商品",
                String.valueOf(saleOrder.getId()),
                mp.getApiKey(),
                opennId
        );
    }


    /**
     * 企业支付
     *
     * @author: 路江
     * @date 2018-10-22
     * @param mchMpPay
     * @param request
     * @throws Exception
     */
    @Override
    public Map<String, Object> mchMpPay(MchMpPay mchMpPay, HttpServletRequest request) throws Exception {
        Map<String, Object> result = new HashMap<>(16);
        //校验登录用户是否是小程序
        CoreUser currentUser = UserUtil.getUser();
        try {
            if (Objects.isNull(currentUser) || !StringUtils.equals(currentUser.getLoginType(), CURRENT_LOGIN_TYPE_MP)) {
                throw new ServiceException("MEMBER-010");
            }
            // 红包支付总开关,如果关闭则停止后续所有动作
            String isPay = PropertyUtil.getCropProperty("isMchPay", currentUser.getLoginCorpId());
            String n = "N";
            if (n.equals(isPay)) {
                throw new ServiceException("MEMBER-011");
            }
            // 验证超频访问
            MpPayTools.processEntrance(currentUser, MpPayConstants.OVER_FREQUENCY_REQUEST);

            //检验活动信息
            SaleActivity saleActivity = new SaleActivity();
            saleActivity.setId(mchMpPay.getActivityId());
            // 验证活动及红包信息
            Coupons coupons = saleActivityService.checkRedPackData(saleActivity, UserUtil.getUser().getId());

            //根据获奖几率和金额类型获取红包金额
            Double money = saleActivityService.getRedPackAmount(coupons);
            if (money == 0.0) {
                mchMpPay.setAmount(0);
                createCollectRecordAndUpdateCoupons(mchMpPay, coupons);
                throw new ServiceException("MEMBER-012");
            }
            // 红包领取设置:校验单个红包最大限额
            if (MpPayTools.checkMaxDrawAmount(money)) {
                throw new ServiceException("MEMBER-013");
            }
            // 设置红包金额
            int randomMoney = (int) (money * 100);
            // 再次校验金额
            Double maxTotalAmoun = coupons.getMaxTotalAmount();
            Double amountTotal = coupons.getTotalAmount() + money;
            if (amountTotal >= maxTotalAmoun) {
                throw new ServiceException("MEMBER-014");
            }
            // 校验单日付款总金额(不影响后续流程)
            MpPayTools.checkMpSingleDayPayAmount(currentUser);
            // 校验单人单日付款总金额(影响后续流程)
            if (MpPayTools.checkMpSingleDayUserPayAmount(currentUser)) {
                throw new ServiceException("MEMBER-015");
            }
            // 校验单人单日付款总数量(影响后续流程)
            if (MpPayTools.checkMpSingleDayUserPayNum(currentUser)) {
                throw new ServiceException("MEMBER-016");
            }

            // 获取当前用户所在小程序的配置信息
            Mp mp = new Mp();
            mp.setAppEncryptionId(currentUser.getIntegrationId());
            mp = mpService.queryMpInfoByEncryptionId(mp);
            // 生成订单号
            String partnerTradeNo = keyGenerateService.orderNoGenerate();
            // 获取配置参数
            CoPayToWalletPayment coPayToWalletPayment = wxPaymentService.getCoPayToWalletPayment(
                    mp.getAppId(),
                    mp.getMchId(),
                    currentUser.getOpenId(),
                    randomMoney,
                    partnerTradeNo,
                    mp.getApiKey(),
                    PayUtils.ForceCheck.NO_CHECK,
                    null,
                    coupons.getInstru()
            );
            mchMpPay.setAmount(randomMoney);
            //发送红包支付
            result = wxPaymentService.sendCoPayToWalletPaymentRequest(coPayToWalletPayment);
//            result.put(RESULT_CODE, RESULT_SUCCESS);
            // 成功
            if (RESULT_SUCCESS.equals(result.get(RESULT_CODE))) {
                // 新增支付记录，记录在优惠券使用记录表中
                createCollectRecordAndUpdateCoupons(mchMpPay, coupons);
                // 创建客户成功领取红包记录
                accntCampMonitorService.insertClickRecord(mchMpPay.getActivityId(), mchMpPay.getReceiveChannel(), "Collected");
                // 成功后设置红包金额
                Double amount = (double) mchMpPay.getAmount() / 100;
                // 设置单日领取总金额
                MpPayTools.setMpMpSingleDayPayAmount(amount, "MP_SINGLE_DAY_PAY_AMOUNT");
                // 设置单人单日领取总金额
                MpPayTools.setMpMpSingleDayPayAmount(amount, "MP_SINGLE_DAY_PAY_AMOUNT_" + currentUser.getOpenId());
                // 设置单人单日领取总次数
                MpPayTools.setMpMpSingleDayPayNum("MP_SINGLE_DAY_PAY_NUM_" + currentUser.getOpenId());
                result.put("redMoney", amount);
            } else {
                String msg = (String) result.get(RESULT_ERR_CODE_DES);
                if (StringUtils.isBlank(msg)) {
                    msg = "系统繁忙，请稍后再试";
                }
                throw new Exception("" + msg);
            }
        } catch (Exception e) {
            LCLogger.withException(e);
            // 记录下领取失败
            MpPayTools.processEntrance(currentUser, MpPayConstants.FAIL_TO_RECIEVE);
            throw new Exception(e.getMessage());
        }
        return result;
    }

    /**
     * 获取随机金额
     *
     * @author: 路江
     * @date 2018-10-22
     * @return double 金额
     */
    private double setRedMenoy() {
        // 基础参数设置
        //取 0-4的随机数
        int redRandNum = RANDOM.nextInt(12);
        //随机金额
        double randMoney = RED_MONEYS[redRandNum] * 100;
        return randMoney;
    }

    /**
     * 创建红包领取记录
     *
     * @author: 路江
     * @date 2018-10-22
     * @param mchMpPay
     * @param coupons
     * @throws Exception
     */
    private void createCollectRecordAndUpdateCoupons(MchMpPay mchMpPay, Coupons coupons) throws Exception {

        CollectRecord record = new CollectRecord();
        Long receptionId = keyGenerateDao.keyGenerate();
        record.setId(receptionId);
        record.setAccntId(UserUtil.getUser().getId());
        record.setCouponsId(coupons.getId());
        record.setClaimStatus("Used");
        record.setEffectEndTime(coupons.getEffectEndTime());
        record.setEffectStaTime(coupons.getEffectStaTime());
        record.setUseChannel("MiniProgram");
        record.setReceiveChannel(mchMpPay.getReceiveChannel());
        record.setClaimTime(DateUtil.dateToStr(new Date(), ""));
        record.setAmount(((double) mchMpPay.getAmount()) / 100);
        collectRecordService.insert(record);
        //可能会多次更新，需要加锁控制
        int updateRow = couponsService.updateReceivedNum(coupons);
        //如果更新数量不等于1 那么就回滚失败
        // 更新0条
        if (updateRow != 1) {
            throw new ServiceException("MEMBER-017");
        }
    }

    /**
     * 查询支付结果
     *
     * @author: 路江
     * @date 2018-10-22
     * @param mchMpPay
     * @param request
     * @return Map
     * @throws Exception
     */
    @Override
    public Map<String, Object> queryPayResult(MchMpPay mchMpPay, HttpServletRequest request) throws Exception {
        Map<String, Object> result = new HashMap<>(16);
        CoreUser user = UserUtil.getUser();
        //获取Mp对象
        Mp mp = new Mp();
        mp.setAppEncryptionId(user.getIntegrationId());
        mp = mpService.queryMpInfoByEncryptionId(mp);
        CoPayToWalletPayment coPayToWalletPayment = new CoPayToWalletPayment();
        coPayToWalletPayment.setNonceStr(PayUtils.createNonceStr());
        mchMpPay.setSign(wxPaymentService.createCoPayToWalletPaymentSign(coPayToWalletPayment, mp.getApiKey()));
        XStream xstream = new XStream();
        xstream.processAnnotations(mchMpPay.getClass());
        //生成请求参数XML
        String xml = xstream.toXML(mchMpPay);
        xml = xml.replace("__", "_");
        //请求url
        String url = env.getProperty("weixinuri.queryMpMchpayUrl");
        //发送请求
        result = PayUtils.post(xml, url, mchMpPay.getMchid());
        return result;
    }



    /**
     * 业务处理代码
     *
     * @param currentLockKey 锁主键
     * @param mchMpPay
     * @param currentUser    当前用户
     * @param request        当前请求
     * @throws Exception
     */
    private void closeRedCouponServer(String currentLockKey, MchMpPay mchMpPay, CoreUser currentUser, HttpServletRequest request) throws Exception {
        //设置有效期5秒
        int expireTime = 2000;
        RedisApiUtils.expire(currentLockKey, expireTime);
        logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ] 抢占成功有效期: [" + expireTime + " ]");
        // 校验红包基础信息
        int randomMoney = 0;
        try {
            SaleActivity saleActivity = new SaleActivity();
            saleActivity.setId(mchMpPay.getActivityId());
            Coupons coupons = saleActivityService.checkRedPackData(saleActivity, currentUser.getAcctId());
            // 设置红包金额
            randomMoney = (int) setRedMenoy();
            // 配置参数
//            mchMpPay = this.mchMpWxPay(mchMpPay, request, currentUser, randomMoney, coupons.getInstru());
            // 发送红包支付
//            Map<String, Object> result = sendPayRed(mchMpPay);
            // 模拟发送红包成功
            Map<String, Object> result = new HashMap<>(8);
            //result.put(RESULT_CODE, RESULT_SUCCESS);
            // 成功
            if (RESULT_SUCCESS.equals(result.get(RESULT_CODE))) {
                // 新增支付记录，记录在优惠券使用记录表中
                createCollectRecordAndUpdateCoupons(mchMpPay, coupons);
            } else {
                String msg = (String) result.get(RESULT_ERR_CODE_DES);
                if (StringUtils.isBlank(msg)) {
                    msg = "系统繁忙，请稍后再试";
                }
                throw new BasicServiceException("" + msg);
            }
           /* //可能会多次更新，需要加锁控制
            int updateRow = couponsService.updateReceivedNum(coupons);

            //如果更新数量不等于1 那么就回滚失败
            // 更新0条·12345
            if (updateRow != 1) {
                logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ] 抢占成功,红包券累加更新失败条数: [" + updateRow + " ]");
                throw new BasicServiceException("抢红包失败,请尝试");
            }*/
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new BasicServiceException(e.getMessage());
        } finally {
            RedisApiUtils.del(currentLockKey);
            logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]释放抢红包锁:[ " + currentLockKey + " ] 成功");
        }
    }

    /**
     * 并发企业支付
     * 控制同一用户多次抢红包
     *
     * @param mchMpPay
     * @param request  当前请求对象
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Map<String, Object> concurrentMchMpPay(MchMpPay mchMpPay, HttpServletRequest request) throws Exception {
        //校验登录用户是否是小程序
        CoreUser currentUser = UserUtil.getUser();
        if (Objects.isNull(currentUser) || !StringUtils.equals(currentUser.getLoginType(), CURRENT_LOGIN_TYPE_MP)) {
            throw new ServiceException("MEMBER-010");
        }
        logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包开始.....");
        Long memberId = currentUser.getId();
        Long activityId = mchMpPay.getActivityId();
        Long couponsId = mchMpPay.getCouponsId();
        // 锁主键 memberId_activityId_couponsId
        String currentLockKey = memberId + "_" + activityId + "_" + couponsId;
        logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ]");
        Map<String, Object> result = new HashMap<>(8);
        // 添加锁的超时时间  六十秒
        long lockTimeout = 60000;
        Long setnxResult = RedisApiUtils.setnx(currentLockKey, String.valueOf(System.currentTimeMillis() + lockTimeout));
        if (setnxResult != null && setnxResult.intValue() == 1) {
            logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ] 抢占成功，进入业务");
            // 业务处理
            closeRedCouponServer(currentLockKey, mchMpPay, currentUser, request);
            result.put("redMoney", mchMpPay.getAmount());
            return result;
        } else {
            logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ] 抢占失败，检测是否进入死锁");
            String getResult = RedisApiUtils.get(currentLockKey);
            // 该键值存在，并且已经过期
            if (getResult != null && System.currentTimeMillis() > Long.parseLong(getResult)) {

                // 进行锁的有效期设置
                String oldResult = RedisApiUtils.getSet(currentLockKey, String.valueOf(System.currentTimeMillis() + lockTimeout));
                // 获取的旧值不为空，并且 该旧值B等于get中获取的值A
                if (StringUtils.isBlank(oldResult) || (StringUtils.isNotBlank(oldResult) && StringUtils.equals(getResult, oldResult))) {
                    logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ]抢红包锁:[ " + currentLockKey + " ] 检测抢占成功");
                    closeRedCouponServer(currentLockKey, mchMpPay, currentUser, request);
                    result.put("redMoney", mchMpPay.getAmount());
                    return result;
                } else {
                    logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ] 没有获取到分布式锁:[ " + currentLockKey + " ] ");
                }
            } else {
                logger.info("小程序当前登陆用户[ " + currentUser.getId() + " ] 没有获取到分布式锁:[ " + currentLockKey + " ] ");
            }
        }
        return result;
    }

    @Override
    public Map<String, Object> queryMemInfo(Long id) throws Exception {
        Map<String, Object> map = new HashMap<>(8);
        try {
            if (null == id) {
                throw new ServiceException("MEMBER-018");
            }
            MpMember mpMember = new MpMember();
            mpMember.setId(id);
            mpMember = mpmemberMapper.queryById(mpMember);
            MemberAccount memberAccount = new MemberAccount();
            memberAccount.setPageFlag(false);
            memberAccount.setMemberId(id);
            memberAccount.setMemprimary("Y");
//            List<MemberAccount> memberAccountList = memberAccountService.queryByExamplePage(memberAccount);
            List<MemberAccount> memberAccountList = new ArrayList<>();
            if (memberAccountList != null) {
                mpMember.setMemberAccountList(memberAccountList);
            }
            map.put("newRow", mpMember);
            map.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new BasicServiceException(e.getMessage());
        }
        return map;
    }
}

